/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package se.sll.service.catalogue.importer.extract;

import se.sll.service.catalogue.model.vm.Vardgivare;
import se.sll.service.catalogue.model.vm.Vantetid;
import se.sll.service.catalogue.model.vm.Atgard;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.camel.Exchange;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import se.sll.service.catalogue.model.vm.VardgivarDel;

/**
 *
 * @author khaleddaham
 */
@Slf4j
public class VTGetProcessor {

    private static XPathFactory xPathfactory;
    private final XPath xpath;

    public VTGetProcessor() {
        String hsa_vm_map = "/Users/khaleddaham/NetBeansProjects/sll-servicecatalogue/offers/import/utbudspunkter.csv";
        xPathfactory = XPathFactory.newInstance();
        xpath = xPathfactory.newXPath();
    }

    /**
     *
     * @return @throws XPathExpressionException
     */
    private List<Atgard> getAtgardList(Document doc) throws XPathExpressionException {
        List<Atgard> productList = new ArrayList<>();
        String expression = "//Atgard";
        XPathExpression expr = xpath.compile(expression);
        NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
        for (int i = 0; i < nl.getLength(); i++) {
            Node childNode = nl.item(i);
            NamedNodeMap attributes = childNode.getAttributes();
            Atgard product = new Atgard();
            product.setAtgardID(attributes.getNamedItem("AtgardID").getTextContent());
            product.setAtgardNamn(attributes.getNamedItem("AtgardNamn").getTextContent());
            product.setAtgardTypID(attributes.getNamedItem("AtgardTypID").getTextContent());
            try {
                product.setForklaring(attributes.getNamedItem("Forklaring").getTextContent());
            } catch (Exception ex) {
                product.setForklaring("");
            }
            productList.add(product);
        }
        return productList;
    }

    private String formatDate(String input) throws ParseException {
        // 2012-05-30 00:00:00.000
        SimpleDateFormat originalFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        SimpleDateFormat targetFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = originalFormat.parse(input);
        return targetFormat.format(date);
    }

    /**
     * <Vantetid VantetidID="1189" AtgardID="51" VardgivarID="233"
     * VardgivarDelID="12" VantetidTomDatum="2012-12-31 00:00:00.000" Fritext=""
     * VtidMottag="5" VtidMottagFortur="5" VtidOperationMottag="5"
     * VtidOperationMottagFortur="5" UppgAnsvarig="Ninna Robéus"
     * AndradDatum="2012-11-22 00:00:00.000" AndradSign="niro" /> @return
     *
     * @throws XPathExpressionException
     */
    private List<Vantetid> getVantetidList(Document doc) throws XPathExpressionException {
        NodeList atgardList = doc.getElementsByTagName("Atgard");
        NodeList vardgivarDelList = doc.getElementsByTagName("VardgivarDel");
        NodeList vardgivareList = doc.getElementsByTagName("Vardgivare");
        Map<String, Atgard> atgardMap = getAtgardMap(atgardList);
        Map<String, VardgivarDel> vardgivarDelMap = getVardgivarDelMap(vardgivarDelList);
        Map<String, Vardgivare> vardgivareMap = getVardgivarMap(vardgivareList);

        List<Vantetid> waitingTimeList = new ArrayList<>();
        String expression = "//Vantetid";

        XPathExpression expr = xpath.compile(expression);
        NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
        for (int i = 0; i < nl.getLength(); i++) {
            Node childNode = nl.item(i);
            NamedNodeMap attributes = childNode.getAttributes();
            Vantetid waitingTime = new Vantetid();

            waitingTime.setAndradDatum(attributes.getNamedItem("AndradDatum").getTextContent());
            waitingTime.setAndradSign(attributes.getNamedItem("AndradSign").getTextContent());
            waitingTime.setFritext(attributes.getNamedItem("Fritext").getTextContent());
            waitingTime.setUppgAnsvarig(attributes.getNamedItem("UppgAnsvarig").getTextContent());
            waitingTime.setVantetidID(attributes.getNamedItem("VantetidID").getTextContent());
            try {
                waitingTime.setVantetidTomDatum(formatDate(attributes.getNamedItem("VantetidTomDatum").getTextContent()));
            } catch (ParseException ex) {
                log.info(ex.getMessage(), ex);
            }

            waitingTime.setAtgard(
                    atgardMap.get(
                            attributes.getNamedItem("AtgardID").getTextContent()));
            waitingTime.setVardgivarDel(
                    vardgivarDelMap.get(
                            attributes.getNamedItem("VardgivarDelID").getTextContent()));
            waitingTime.setVardgivar(vardgivareMap.get(
                    attributes.getNamedItem("VardgivarID").getTextContent()));
            try {
                waitingTime.setVtidMottag(attributes.getNamedItem("VtidMottag").getTextContent());
            } catch (Exception ex) {
                waitingTime.setVtidMottag(null);
            }
            try {
                waitingTime.setVtidMottagFortur(attributes.getNamedItem("VtidMottagFortur").getTextContent());
            } catch (Exception ex) {
                waitingTime.setVtidMottagFortur(null);
            }
            try {
                waitingTime.setVtidOperationMottag(attributes.getNamedItem("VtidOperationMottag").getTextContent());
            } catch (Exception ex) {
                waitingTime.setVtidOperationMottag(null);
            }
            try {
                waitingTime.setVtidOperationMottagFortur(attributes.getNamedItem("VtidOperationMottagFortur").getTextContent());
            } catch (Exception ex) {
                waitingTime.setVtidOperationMottagFortur(null);
            }
            try {
                waitingTime.setVtidOperation(attributes.getNamedItem("VtidOperation").getTextContent());
            } catch (Exception ex) {
                waitingTime.setVtidOperation(null);
            }
            try {
                waitingTime.setVtidOperationFortur(attributes.getNamedItem("VtidOperationFortur").getTextContent());
            } catch (Exception ex) {
                waitingTime.setVtidOperationFortur(null);
            }

            waitingTimeList.add(waitingTime);
        }
        return waitingTimeList;
    }

    /**
     * <Vardgivare VardgivarID="580" VardgivarNamn="AB Hearing" KommunDelID="23"
     * Postnr="11224 Stockholm" Postadress="Kaplansbacken 5"
     * Besokadress="Kaplansbacken 5" Telefon="" Hemsida=""
     * epostadress="mail@hearing.se" AndradDatum="2012-11-12 00:00:00.000"
     * AndradSign="1n04" /> @return @throws XPathExpressionException
     */
    private List<Vardgivare> getCareUnits(Document doc) throws XPathExpressionException {
        List<Vardgivare> careUnitList = new ArrayList<>();
        String expression = "//Vardgivare";
        XPathExpression expr = xpath.compile(expression);
        NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
        for (int i = 0; i < nl.getLength(); i++) {
            Node childNode = nl.item(i);
            NamedNodeMap attributes = childNode.getAttributes();
            Vardgivare careUnit = new Vardgivare();

            careUnit.setAndradDatum(attributes.getNamedItem("AndradDatum").getTextContent());
            careUnit.setAndradSign(attributes.getNamedItem("AndradSign").getTextContent());
            careUnit.setBesokadress(attributes.getNamedItem("Besokadress").getTextContent());
            try {
                careUnit.setEpostadress(attributes.getNamedItem("Epostadress").getTextContent());
            } catch (Exception ex) {
                careUnit.setEpostadress(null);
            }
            careUnit.setHemsida(attributes.getNamedItem("Hemsida").getTextContent());
            careUnit.setKommunDelID(attributes.getNamedItem("KommunDelID").getTextContent());
            careUnit.setPostadress(attributes.getNamedItem("Postadress").getTextContent());
            careUnit.setPostnr(attributes.getNamedItem("Postnr").getTextContent());
            careUnit.setTelefon(attributes.getNamedItem("Telefon").getTextContent());
            careUnit.setVardgivarID(attributes.getNamedItem("VardgivarID").getTextContent());
            careUnit.setVardgivarNamn(attributes.getNamedItem("VardgivarNamn").getTextContent());
//            careUnit.setVardgivarPartNamn(attributes.getNamedItem("VardgivarPartNamn").getTextContent());

            careUnitList.add(careUnit);
        }
        return careUnitList;
    }

    /**
     *
     * @param exchange
     */
    public void process(Exchange exchange) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = null;
        Document doc = null;
        Map<String, Object> body = new HashMap<>();
        try {
            builder = factory.newDocumentBuilder();
        } catch (ParserConfigurationException ex) {
            log.error(ex.getMessage(), ex);
        }
        try {
            doc = builder.parse((String) exchange.getIn().getBody());
        } catch (SAXException ex) {
            log.error(ex.getMessage(), ex);
        } catch (IOException ex) {
            log.error(ex.getMessage(), ex);
        }
        try {
            List<Atgard> productList = getAtgardList(doc);
            body.put("product", productList);
        } catch (XPathExpressionException ex) {
            log.error(ex.getMessage(), ex);
        }
        try {
            List<Vantetid> waitingTimes = getVantetidList(doc);
            body.put("capacity", waitingTimes);
        } catch (XPathExpressionException ex) {
            log.error(ex.getMessage(), ex);
        }
        try {
            List<Vardgivare> careUnits = getCareUnits(doc);
            body.put("offer", careUnits);
        } catch (XPathExpressionException ex) {
            log.error(ex.getMessage(), ex);
        }
        exchange.getIn().setBody(body);
    }

    private Map<String, Atgard> getAtgardMap(NodeList atgardList) {
        Map<String, Atgard> map = new HashMap<>();
        for (int i = 0; i < atgardList.getLength(); i++) {
            Atgard obj = new Atgard();
            obj.setAtgardID(atgardList.item(i).getAttributes().getNamedItem("AtgardID").getTextContent());
            obj.setAtgardNamn(atgardList.item(i).getAttributes().getNamedItem("AtgardNamn").getTextContent());
            obj.setAtgardTypID(atgardList.item(i).getAttributes().getNamedItem("AtgardTypID").getTextContent());
            map.put(obj.getAtgardID(), obj);
        }
        return map;
    }

    private Map<String, VardgivarDel> getVardgivarDelMap(NodeList nl) {
        Map<String, VardgivarDel> map = new HashMap<>();
        for (int i = 0; i < nl.getLength(); i++) {
            VardgivarDel obj = new VardgivarDel();
            obj.setVardgivardelID(nl.item(i).getAttributes().getNamedItem("VardgivardelID").getTextContent());
            obj.setVardgivardelNamn(nl.item(i).getAttributes().getNamedItem("VardgivardelNamn").getTextContent());
            map.put(obj.getVardgivardelID(), obj);
        }
        return map;
    }

    private Map<String, Vardgivare> getVardgivarMap(NodeList nl) {
        Map<String, Vardgivare> map = new HashMap<>();
        for (int i = 0; i < nl.getLength(); i++) {
            Vardgivare obj = new Vardgivare();
            obj.setVardgivarID(nl.item(i).getAttributes().getNamedItem("VardgivarID").getTextContent());
            obj.setVardgivarNamn(nl.item(i).getAttributes().getNamedItem("VardgivarNamn").getTextContent());
            map.put(obj.getVardgivarID(), obj);
        }
        return map;
    }
}
